package cn.vire.electric.simulation.websocket.config;

import cn.vire.electric.simulation.config.interceptor.AuthenticationInterceptor;
import cn.vire.electric.simulation.pojo.LoginUserDto;
import cn.vire.electric.simulation.utils.JwtHelper;
import cn.vire.electric.simulation.websocket.SimulateWebSocketHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @Description: websocket握手时的拦截器
 */
@Component
@Slf4j
@ConditionalOnProperty(value = {"biz.server.web-socket.enable"})
public class WebSocketInterceptor implements HandshakeInterceptor {

    /**
     * Protocol协议名称
     */
    private String protocol = "vire";
    @Value("${biz.server.web-socket.max-connections:10}")
    private Integer maxConnections;

    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        log.info("websocket握手开始");
        if (SimulateWebSocketHandler.handBizSessionMap.size() >= maxConnections) {
//        if (SimulateWebSocketHandler.connNum.get() >= maxConnections) {
            serverHttpResponse.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
            return false;
        }
        if (serverHttpRequest instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) serverHttpRequest;
            HttpServletRequest request = servletServerHttpRequest.getServletRequest();
            String token = servletServerHttpRequest.getServletRequest().getParameter(AuthenticationInterceptor.USER_TOKEN_HEAD);
//            String token = request.getHeader(AuthenticationInterceptor.USER_TOKEN_HEAD);
            log.info("当前握手用户[{} = {}]", AuthenticationInterceptor.USER_TOKEN_HEAD, token);
            if (StringUtils.isEmpty(token) && request.getCookies() != null && request.getCookies().length > 0) {
                for (Cookie cookie : request.getCookies()) {
                    if (AuthenticationInterceptor.USER_TOKEN_HEAD.equals(cookie.getName())) {
                        token = cookie.getValue();
                        log.info("当前握手用户cookie[{} = {}]", AuthenticationInterceptor.USER_TOKEN_HEAD, token);
                        break;
                    }
                }
            }
            if (StringUtils.isEmpty(token)) {
                serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
                return false;
            }
            try {
                if (JwtHelper.verifyToken(token) != null) {
                    //token 不为空的话直接进行校验
                    LoginUserDto loginUserDto = JwtHelper.getUserInfo(token);
                    log.info("解析用户[{} = {} ]", AuthenticationInterceptor.USER_TOKEN_HEAD, loginUserDto);
                    map.put("user", loginUserDto);
                    //设置响应头,只处理{protocol}协议请求
                    ((ServletServerHttpResponse) serverHttpResponse).getHeaders().add("Sec-WebSocket-Protocol", protocol);
                    log.info("websocket握手成功,放行");
                    return true;
                }
            } catch (Exception e) {
                log.error("解析token异常捕获", e);
                serverHttpResponse.setStatusCode(HttpStatus.BAD_REQUEST);
                return false;
            }
        }
        log.error("websocket握手失败");
        serverHttpResponse.setStatusCode(HttpStatus.BAD_REQUEST);
        return false;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
        log.info("websocket握手结束");
    }
}
